home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / boot / netBoot.new / sys / reset.c < prev    next >
C/C++ Source or Header  |  1990-12-19  |  14KB  |  447 lines

  1.  
  2. /*
  3.  * @(#)reset.c 1.1 86/09/27
  4.  * Copyright (c) 1986 by Sun Microsystems, Inc.
  5.  */
  6.  
  7. /*
  8.  * reset.c
  9.  *
  10.  * Brings the system from its knees (set up by assembler code at power-on)
  11.  * to its feet.
  12.  */
  13.  
  14. #include "../sun3/sunmon.h"
  15. #include "../sun3/cpu.map.h"
  16. #include "../sun3/cpu.addrs.h"
  17. #include "../sun3/cpu.misc.h"
  18. #include "../h/globram.h"
  19. #include "../dev/zsreg.h"
  20. #include "../h/keyboard.h"
  21. #include "../h/sunromvec.h"
  22. #include "../sun3/m68vectors.h"
  23. #include "../h/pginit.h"
  24. #include "../h/montrap.h"
  25. #include "../h/dpy.h"
  26. #include "../h/video.h"
  27. #include "../h/led.h"
  28. #include "../h/setbus.h"
  29. #include "../dev/saio.h"
  30. #include "../h/clock.h"
  31. #include "../h/interreg.h"
  32. #include "../h/enable.h"
  33. #include "../sun3/memerr.h"
  34. #include "../sun3/structconst.h"
  35. #include "../h/eeprom.h"
  36.  
  37. int    trap(), bus_error(), addr_error(), nmi();
  38. void     reset_uart();
  39.  
  40. int cpudelay =  3;
  41.  
  42. /*
  43.  * Table of map entries used to map video back on a watchdog.
  44.  * This is because video might have been running in copy mode 'cuz of
  45.  * Unix.  We take it back since we don't turn on copy mode in the
  46.  * video control reg.
  47.  */
  48. struct pginit videoinit[] = {
  49.     {VIDEOMEM_BASE, 1,        /* Video memory (if we have any) */
  50.         {1, PMP_ALL, VPM_MEMORY, 0, 0, MEMPG_VIDEO}},
  51.     {((char *)VIDEOMEM_BASE)+128*1024, PGINITEND,
  52.         {0, PMP_RO_SUP, VPM_MEMORY, 0, 0, 0}},
  53. };
  54.  
  55.  
  56. /*
  57.  * monreset()
  58.  *
  59.  * Entered from assembler code (trap.s) on all resets, just before we
  60.  * call the command interpreter.  We get to set up all of the I/O
  61.  * devices and most of the rest of the software world.  Memory has been
  62.  * mapped to our preferences, and we are out of boot state.
  63.  * Interrupts cannot occur until we enable them,
  64.  * but we can still get bus/address errors, which fetch their vectors from
  65.  * (as yet uninitialized) mappable memory (not prom).
  66.  *
  67.  * For power-on resets, we are in context 0.  Enough working memory is
  68.  * mapped in starting at location 0 to get us going (a few megs).
  69.  * This memory has been initialized to F's.
  70.  *
  71.  * For other resets, FIXME: maps?  Memory is untouched.
  72.  *
  73.  * The argument is an interrupt stack, the same one passed to monitor().
  74.  * Like the one passed to monitor(), we can modify it and this changes
  75.  * external reality (eg, the PC or registers which will be set up for
  76.  * the user program).
  77.  *
  78.  * There are four kinds of resets possible:
  79.  *    EVEC_RESET    Power-on reset (or equivalently, K2 command)
  80.  *    EVEC_KCMD    K1 command from the keyboard
  81.  *    EVEC_BOOTING    B command from the keyboard
  82.  *    EVEC_DOG    Watchdog reset after CPU double bus fault
  83.  *
  84.  * The Dog is the scariest reset, since we want to disturb as little info
  85.  * as possible (for debugging), but also want to bring the system back
  86.  * under control.  The RESET is where we have to be thorough; bad boards
  87.  * will often make it this far and we have to give good diagnosis of
  88.  * what we find.  The other two are similar to each other and relatively easy.
  89.  */
  90.  
  91. monreset(monintstack)
  92.     struct monintstack monintstack;
  93. {
  94.     register long *et;
  95.     register int time;
  96.     int i, baud = 0;
  97.     bus_buf bbuf;        /* Buffer for bus error recovery */
  98.  
  99.     set_enable(get_enable() | ENA_NOTBOOT | ENA_SDVMA);
  100.  
  101.     if (r_vector != EVEC_DOG) {
  102.         r_context = 0;
  103.  
  104.         for (et = (long *)TRAPVECTOR_BASE, i = NUM_EVECS; i ; i--)
  105.             *et++ = (long) trap;
  106.  
  107.         et = (long *)TRAPVECTOR_BASE;
  108.         *et++ = (long) gp;        /* 0 = ptr to Globals area */
  109.         *et++ = (long) romp;        /* 4 = ptr to Transfer Vector */
  110.  
  111.         *et++ = (long) bus_error;    /* 8 = bus error routine */
  112.         *et++ = (long) addr_error;    /* C = address error routine */
  113.         (void) set_evec(EVEC_LEVEL7, nmi);
  114.     }
  115.  
  116.     if (r_vector == EVEC_RESET || r_vector == EVEC_BOOT_EXEC
  117.         || r_vector == EVEC_MENU_TSTS) {
  118.         gp->g_inzscc = SERIAL0_BASE; /* Initialize the UART's */
  119.         gp->g_outzscc = SERIAL0_BASE;
  120.     }
  121.  
  122.     /*
  123.      * Write all the assorted initialization commands to both
  124.      * halves of the UART chip.
  125.      */
  126.     reset_uart(&SERIAL0_BASE[0].zscc_control, 1);
  127.     reset_uart(&SERIAL0_BASE[1].zscc_control, 0);
  128.  
  129.     /*
  130.      *    Check EEPROM for SCC Port A baud rate
  131.          */
  132.     if (EEPROM->ee_diag.eed_ttya_def.eet_sel_baud == EET_SELBAUD) {
  133.         baud = (EEPROM->ee_diag.eed_ttya_def.eet_hi_baud << 8) +
  134.                 EEPROM->ee_diag.eed_ttya_def.eet_lo_baud;
  135.         SERIAL0_BASE[1].zscc_control = 12;
  136.             DELAY(2);
  137.             SERIAL0_BASE[1].zscc_control = ZSTIMECONST(ZSCC_PCLK, baud);
  138.             DELAY(2);
  139.             SERIAL0_BASE[1].zscc_control = 13;
  140.             DELAY(2);
  141.             SERIAL0_BASE[1].zscc_control = (ZSTIMECONST(ZSCC_PCLK, baud)) >> 8;
  142.             DELAY(2);
  143.     }
  144.  
  145.     /*
  146.          *      Check EEPROM for SCC Port B baud rate
  147.          */ 
  148.         if (EEPROM->ee_diag.eed_ttyb_def.eet_sel_baud == EET_SELBAUD) {
  149.             baud = (EEPROM->ee_diag.eed_ttyb_def.eet_hi_baud << 8) +
  150.                     EEPROM->ee_diag.eed_ttyb_def.eet_lo_baud;
  151.             SERIAL0_BASE[0].zscc_control = 12;
  152.             DELAY(2);
  153.             SERIAL0_BASE[0].zscc_control = ZSTIMECONST(ZSCC_PCLK, baud);
  154.             DELAY(2);
  155.             SERIAL0_BASE[0].zscc_control = 13;
  156.             DELAY(2);
  157.             SERIAL0_BASE[0].zscc_control = (ZSTIMECONST(ZSCC_PCLK, baud)) >> 8;
  158.             DELAY(2);
  159.         }
  160.  
  161.     GXBase = (int)VIDEOMEM_BASE;
  162.     gp->g_font = (unsigned short (*)[CHRSHORTS-1])FONT_BASE;
  163.  
  164. #ifndef GRUMMAN1 /* no video for grumman */
  165.     if ((r_vector != EVEC_RESET) && (r_vector != EVEC_BOOT_EXEC)
  166.         && (r_vector != EVEC_MENU_TSTS)) {
  167.         setupmap(videoinit);    /* Initialize video mem map */
  168.         finit (ax, ay);
  169.     }
  170. #endif GRUMMAN1
  171.  
  172. #ifndef    SIRIUS
  173.     MEMORY_ERR_BASE->mr_er = PER_INTENA | PER_CHECK; /* turn on parity */
  174. #else
  175.     MEMORY_ERR_BASE->mr_er = EER_INTENA ;  /* turn off ecc error rep */
  176. #endif    SIRIUS
  177.     if (r_vector != EVEC_DOG) {
  178.         reset_alloc();  
  179.         CLOCK_BASE->clk_cmd = CLK_CMD_NORMAL;
  180.     }
  181.  
  182.     /*
  183.      * This hardware is sufficiently delicate that we need to follow
  184.      * this order:
  185.      *    Reset interrupt-catching flops
  186.      *    Clear and disable TOD chip interrupts
  187.      *    Enable interrupt-catching flop(s)
  188.      *    Enable TOD chip interrupts
  189.      */
  190.     gp->g_nmiclock = 0;    /* initialize nmi counter */
  191.     *INTERRUPT_BASE &= ~(IR_ENA_CLK7 | IR_ENA_CLK5);  /* Unhang flops */
  192.     CLOCK_BASE->clk_intrreg = 0;        /* Disable TOD ints */
  193.     i = CLOCK_BASE->clk_intrreg;        /* Maybe clr pending int */
  194.     *INTERRUPT_BASE |=  IR_ENA_CLK7;    /* Prime the flops */
  195.     CLOCK_BASE->clk_intrreg = CLK_INT_HSEC;    /* Now allow TOD ints */
  196.  
  197.     /*
  198.      * These are used by the NMI routine.
  199.      */
  200.     gp->g_debounce = ZSRR0_BREAK;    /* For remembering BREAK state */
  201.     gp->g_init_bounce = 0x0;        /* Initialize BREAK state */
  202.  
  203. #ifndef GRUMMAN1 /* no keyboard/mouse for grumman */
  204.  
  205.     if (r_vector == EVEC_DOG || r_vector == EVEC_RESET || 
  206.         r_vector == EVEC_BOOT_EXEC || r_vector ==EVEC_MENU_TSTS ||
  207.         r_vector == EVEC_KCMD || r_vector == EVEC_BOOTING)
  208.           {
  209.         /* Setup mouse SCC channel - MSP 10/5/85 */
  210.         reset_uart(&KEYBMOUSE_BASE[0].zscc_control, 0);    
  211.  
  212.         gp->g_keybzscc = &KEYBMOUSE_BASE[1];
  213.         initbuf (gp->g_keybuf, KEYBUFSIZE); /* Set up buffer pointers */
  214.  
  215.         reset_uart(&gp->g_keybzscc->zscc_control, 0);
  216.         gp->g_keybzscc->zscc_control = 12;
  217.         DELAY(2);
  218.         gp->g_keybzscc->zscc_control = ZSTIMECONST(ZSCC_PCLK, 1200);
  219.         DELAY(2);
  220.         gp->g_keybzscc->zscc_control = 13;
  221.         DELAY(2);
  222.         gp->g_keybzscc->zscc_control = (ZSTIMECONST(ZSCC_PCLK,1200))>>8;
  223.         DELAY(2);
  224.     } 
  225.  
  226.     if (r_vector == EVEC_RESET || r_vector == EVEC_BOOT_EXEC ||
  227.            r_vector == EVEC_MENU_TSTS) {
  228.         gp->g_insource = INKEYB;        /* set pointer to keyboard */
  229.         gp->g_outsink = OUTSCREEN;    /* set pointer to video */
  230.     }
  231. #endif GRUMMAN1
  232.  
  233. #ifdef GRUMMAN1 /* Grumman has only ports A & B so we force it to A */
  234.     if (r_vector == EVEC_RESET || r_vector == EVEC_BOOT_EXEC ||
  235.            r_vector == EVEC_MENU_TSTS) {
  236.         gp->g_insource = INUARTA;        /* set pointer to keyboard */
  237.         gp->g_outsink =  INUARTA;    /* set pointer to video */
  238.     }
  239. #endif GRUMMAN1
  240.  
  241.     /*
  242.          * Now that we need to take NMI's, set up the NMI vector and
  243.          * enable interrupts.  We need to set up the vector in case this
  244.          * is a watchdog; Unix now steals it from us, and the keyboard
  245.          * is unusable after a Dog.
  246.          */
  247.         (void) set_evec (EVEC_LEVEL7, nmi);
  248.         *INTERRUPT_BASE |= IR_ENA_INT;  /* Enable any interrupts */
  249.  
  250. #ifndef GRUMMAN1 /* no choice for basic io just use port a */
  251.  
  252.     if (r_vector == EVEC_RESET || r_vector == EVEC_BOOT_EXEC ||
  253.         r_vector == EVEC_MENU_TSTS) {
  254.         gp->g_keystate = STARTUP;    /* initialize state machine */
  255.                 gp->g_keybid = KB_UNKNOWN;    /* set flag to unknown keyb */
  256.  
  257.         for (i = 100; i >= 0; i--) {
  258.             if (sendtokbd(KBD_CMD_RESET)) {
  259.                 time = 1000 + gp->g_nmiclock;  /* wait 100 ms */
  260.                 do {
  261.                     if (gp->g_keybid != KB_UNKNOWN) 
  262.                         break;
  263.                 } while (time > gp->g_nmiclock);
  264.                 break;
  265.             }
  266.         }
  267.     
  268.            gp->g_outsink = OUTSCREEN;   /* Copy to video */
  269.            finit (0, 0); 
  270.            fwritestr ("\f", 1); /* Clear screen */
  271.   
  272.                 if (r_vector != EVEC_MENU_TSTS) {
  273.             if(EEPROM->ee_diag.eed_console == EED_CONS_TTYA) {
  274.                 banner();
  275.                                 printf ("EEPROM: Using RS232 A port.\n");
  276.                     gp->g_outsink = gp->g_insource = INUARTA;
  277.                 banner_test();
  278.             }
  279.             else if (EEPROM->ee_diag.eed_console == EED_CONS_TTYB) {
  280.                 banner();
  281.                                 printf ("EEPROM: Using RS232 B port.\n");
  282.                     gp->g_outsink = gp->g_insource = INUARTB;
  283.                 banner_test();
  284.               }
  285.               else if (gp->g_keybid == KB_UNKNOWN) {
  286.                 gp->g_insource = INUARTA;  /* serial input */
  287.                 banner_test();
  288.                 printf("No keyboard found: Using RS232 Port A as input!\n");
  289.               }
  290.               else {
  291.                     gp->g_insource = INKEYB;
  292.                             banner_test();
  293.               }
  294.         }
  295.         else {
  296.             if (gp->g_echoinput == 0x12) {
  297.                 gp->g_insource = INKEYB;
  298.             } else {
  299.                 gp->g_insource = gp->g_sccflag;
  300.                                 gp->g_outsink = gp->g_sccflag;
  301.             }
  302.             }
  303.         initgetkey();
  304.     }
  305. #endif GRUMMAN1
  306.  
  307. #ifdef GRUMMAN1    /* do this init outside the if block if this is grumman */
  308.         initgetkey();
  309. #endif GRUMMAN1
  310.  
  311.     if (r_vector == EVEC_DOG) {
  312.         initgetkey();
  313.                 return;
  314.     }
  315.  
  316.     r_usp = gp->g_memorysize;    /* reset User Stack pointer */
  317.  
  318.     {
  319.         extern  void  vector_default();
  320.         gp->g_vector_cmd = vector_default;
  321.     }
  322.  
  323.     gp->g_breaking = 0;    /* no break in progress */
  324.     gp->g_breakaddr = 0;    /* initialize break address */
  325.     return;
  326. }
  327.  
  328. /*
  329.  *    This routine will only display the banner in diagnostic mode, but
  330.  *    it will run a memory test in normal mode.  The memory test has
  331.  *    been added after the banner because of its length of time when
  332.  *    the video screen looks dead.
  333.  */
  334. banner_test() {
  335.     int    beg_addr, limit, size;
  336.  
  337.     banner();                /* Display the banner */
  338.  
  339.     /* If Non-Diagnostic mode, run this memrory test */
  340.  
  341. #ifndef M25
  342.     if ((get_enable() & 0x01) == 0) {
  343.        if ((EEPROM->ee_diag.eed_memtest << 20) < gp->g_memoryavail) {
  344.         limit = EEPROM->ee_diag.eed_memtest << 20;
  345.         size = EEPROM->ee_diag.eed_memtest;
  346.        } else {
  347.         limit = gp->g_memoryavail;
  348.         size = (gp->g_memoryavail + 0x4000) >> 20;
  349.        }
  350.  
  351.        printf("\nTesting %d Megabytes of Memory ... ", size);
  352.  
  353.        for (beg_addr = 0; beg_addr < limit; beg_addr += MAINMEM_MAP_SIZE) {
  354.         if ((beg_addr + MAINMEM_MAP_SIZE) >= limit) {     /* limit? */
  355.            test_mem(beg_addr, limit);
  356.             break;
  357.         } else {
  358.               test_mem(beg_addr, beg_addr + MAINMEM_MAP_SIZE); 
  359.         }
  360.         open_window(beg_addr + MAINMEM_MAP_SIZE);
  361.        }
  362.        printf("Completed.\n\n");
  363.        close_window();
  364.     }
  365. #endif M25
  366. }
  367.  
  368. /*
  369.  *    This routine is intended to test memory from the address
  370.  *    passed into it to the limit passed into it.  This will
  371.  *      test at most 8 Megabytes at a time.
  372.  */
  373. test_mem(addr, limit) 
  374.     int    addr, limit;
  375. {
  376.         int     pass, end_addr, errflag, feedback = 0, pattern = 0x5A972C5A;  
  377.     int    start_addr;
  378.         char    *ind = "-\\|/";
  379.  
  380.     for (pass = 0; pass < 6; pass++) {
  381.             if (pass == 2)
  382.                 pattern = 0x5A5A972C;    /* Set the pattern for 2nd pass */
  383.             if (pass == 4)
  384.                 pattern = 0x2C5A5A97;    /* Set the pattern for 3rd pass */
  385.  
  386.             /*  Test 1 Megabyte unless it will hit the global variables */
  387.         start_addr = addr;
  388.         for (; start_addr < limit; start_addr += 0x100000) {
  389.                 printf("%c\b", ind[feedback++ % 4]);        /* show life */
  390.              if ((end_addr = start_addr + 0x100000) > limit)    /* limit? */
  391.                    end_addr = limit;
  392.  
  393.                 if ((pass % 2) == 0)
  394.                    errflag = mod3write(start_addr, end_addr, pattern); /* WRITE */
  395.                 else
  396.                    errflag = mod3read(start_addr, end_addr, pattern);  /* READ  */
  397.  
  398.         /* Check for data compare error */
  399.  
  400.             if (errflag == 0) {
  401.                    printf("\n\nMemory Error at 0x%x:", gp->g_mod3addr);
  402.                    printf(" Exp = 0x%x, Obs = 0x%x, Xor = 0x%x!\n", 
  403.                gp->g_mod3exp, gp->g_mod3obs, 
  404.                gp->g_mod3exp ^ gp->g_mod3obs);
  405.                    exit_to_mon();            /* Enter Monitor */
  406.         }
  407.             } 
  408.         }
  409. }
  410.  
  411. /*
  412.  *    This routine opens a window of pages to map 8 Mb of physical memory 
  413.  *    for the memory test.
  414.  */
  415. open_window(paddr)
  416.     int    paddr;
  417. {
  418.     int    virt_addr, pmeg = MAINMEM_MAP_SIZE/(PGSPERSEG * BYTESPERPG);
  419.     unsigned long    pgentry = (0xc0000000 + (paddr >> 13));
  420.  
  421.     /* Map 8 Megabytes of segments linearly */
  422.  
  423.     for (virt_addr = paddr; virt_addr < paddr + MAINMEM_MAP_SIZE; 
  424.          virt_addr += PGSPERSEG * BYTESPERPG)     
  425.                    setsegmap(virt_addr, pmeg++);
  426.  
  427.     /* Map 8 Megabytes of pages to the appropriate physical memory */
  428.     
  429.     for (virt_addr = paddr; virt_addr < paddr + MAINMEM_MAP_SIZE; 
  430.              virt_addr += BYTESPERPG)     
  431.                    setpgmap(virt_addr, pgentry++);
  432. }
  433.  
  434. /*
  435.  *      This routine remaps the segments between memory and the monitor
  436.  *    back to invalid.
  437.  */
  438. close_window()
  439. {
  440.     int    virt_addr;
  441.  
  442.     for (virt_addr = MAINMEM_MAP_SIZE; virt_addr < 16*MAINMEM_MAP_SIZE;
  443.              virt_addr += PGSPERSEG * BYTESPERPG)
  444.                    setsegmap(virt_addr, SEG_INVALID);
  445. }
  446.  
  447.